using System;
using System.Collections.Generic;
using System.Data;
using System.Text.RegularExpressions;
using WegasManagementSystem.DAL;
using WegasManagementSystem.Models;

namespace WegasManagementSystem.BLL
{
    /// <summary>
    /// 工资业务逻辑类
    /// </summary>
    public class SalaryBLL
    {
        private readonly SalaryDAL _salaryDAL;
        private readonly EmployeeDAL _employeeDAL;
        private readonly DepartmentDAL _departmentDAL;
        private readonly AttendanceDAL _attendanceDAL;
        private readonly EmployeeBLL _employeeBLL;

        /// <summary>
        /// 构造函数
        /// </summary>
        public SalaryBLL()
        {
            _salaryDAL = new SalaryDAL();
            _employeeDAL = new EmployeeDAL();
            _departmentDAL = new DepartmentDAL();
            _attendanceDAL = new AttendanceDAL();
            _employeeBLL = new EmployeeBLL();
        }

        #region 工资项目管理

        /// <summary>
        /// 添加工资项目
        /// </summary>
        /// <param name="salaryItem">工资项目对象</param>
        /// <returns>新工资项目ID，失败返回0</returns>
        public int AddSalaryItem(SalaryItem salaryItem)
        {
            if (salaryItem == null)
                throw new ArgumentNullException("salaryItem", "工资项目对象不能为空");

            if (string.IsNullOrEmpty(salaryItem.ItemName))
                throw new ArgumentException("工资项目名称不能为空");

            if (string.IsNullOrEmpty(salaryItem.ItemType))
                throw new ArgumentException("工资项目类型不能为空");

            // 检查工资项目名称是否已存在
            if (_salaryDAL.CheckItemNameExists(salaryItem.ItemName))
                throw new Exception("工资项目名称已存在");

            // 验证工资项目类型
            if (salaryItem.ItemType != "income" && salaryItem.ItemType != "deduction")
                throw new ArgumentException("工资项目类型必须是收入项或扣款项");

            return _salaryDAL.AddSalaryItem(salaryItem);
        }

        /// <summary>
        /// 更新工资项目
        /// </summary>
        /// <param name="salaryItem">工资项目对象</param>
        /// <returns>更新成功返回true，失败返回false</returns>
        public bool UpdateSalaryItem(SalaryItem salaryItem)
        {
            if (salaryItem == null)
                throw new ArgumentNullException("salaryItem", "工资项目对象不能为空");

            if (string.IsNullOrEmpty(salaryItem.ItemName))
                throw new ArgumentException("工资项目名称不能为空");

            if (string.IsNullOrEmpty(salaryItem.ItemType))
                throw new ArgumentException("工资项目类型不能为空");

            // 检查工资项目名称是否已存在（排除当前项目）
            if (_salaryDAL.CheckItemNameExists(salaryItem.ItemName, salaryItem.ItemId))
                throw new Exception("工资项目名称已存在");

            // 验证工资项目类型
            if (salaryItem.ItemType != "income" && salaryItem.ItemType != "deduction")
                throw new ArgumentException("工资项目类型必须是收入项或扣款项");

            return _salaryDAL.UpdateSalaryItem(salaryItem);
        }

        /// <summary>
        /// 删除工资项目
        /// </summary>
        /// <param name="itemId">工资项目ID</param>
        /// <returns>删除成功返回true，失败返回false</returns>
        public bool DeleteSalaryItem(int itemId)
        {
            if (itemId <= 0)
                throw new ArgumentException("无效的工资项目ID");

            return _salaryDAL.DeleteSalaryItem(itemId);
        }

        /// <summary>
        /// 获取所有工资项目
        /// </summary>
        /// <returns>工资项目列表</returns>
        public List<SalaryItem> GetAllSalaryItems()
        {
            return _salaryDAL.GetAllSalaryItems();
        }

        /// <summary>
        /// 根据ID获取工资项目
        /// </summary>
        /// <param name="itemId">工资项目ID</param>
        /// <returns>工资项目对象</returns>
        public SalaryItem GetSalaryItemById(int itemId)
        {
            if (itemId <= 0)
                throw new ArgumentException("无效的工资项目ID");

            return _salaryDAL.GetSalaryItemById(itemId);
        }

        /// <summary>
        /// 获取工资项目类型列表
        /// </summary>
        /// <returns>工资项目类型列表</returns>
        public List<string> GetSalaryItemTypes()
        {
            return _salaryDAL.GetSalaryItemTypes();
        }

        /// <summary>
        /// 获取指定月份的所有工资记录
        /// </summary>
        /// <param name="yearMonth">年月 (YYYY-MM)</param>
        /// <returns>工资记录列表</returns>
        public List<SalaryRecord> GetSalaryRecordsByMonth(string yearMonth)
        {
            if (string.IsNullOrEmpty(yearMonth))
            {
                throw new ArgumentException("年月参数不能为空", nameof(yearMonth));
            }
            
            return _salaryDAL.GetSalaryByMonth(yearMonth);
        }
        
        /// <summary>
        /// 根据部门和月份获取工资信息
        /// </summary>
        /// <param name="deptId">部门ID，0表示所有部门</param>
        /// <param name="yearMonth">年月</param>
        /// <returns>员工工资信息列表</returns>
        public List<SalaryInfo> GetSalaryByDeptAndMonth(int deptId, string yearMonth)
        {
            try
            {
                List<Employee> employees;
                if (deptId == 0)
                {
                    // 获取所有员工
                    employees = _employeeBLL.GetAllEmployees();
                }
                else
                {
                    // 获取指定部门的员工
                    employees = _employeeBLL.GetEmployeesByDepartment(deptId);
                }
                
                List<SalaryInfo> salaryInfoList = new List<SalaryInfo>();
                foreach (var employee in employees)
                {
                    try
                    {
                        SalaryInfo salaryInfo = GetEmployeeSalary(employee.EmpId, yearMonth);
                        if (salaryInfo != null)
                        {
                            salaryInfoList.Add(salaryInfo);
                        }
                    }
                    catch (Exception ex)
                    {
                        // 记录单个员工薪资获取失败，但继续处理其他员工
                        Console.WriteLine($"获取员工{employee.EmpName}({employee.EmpId})的{yearMonth}月工资失败: {ex.Message}");
                    }
                }
                
                return salaryInfoList;
            }
            catch (Exception ex)
            {
                throw new Exception($"获取部门工资信息失败: {ex.Message}", ex);
            }
        }

        #endregion

        #region 工资记录管理

        /// <summary>
        /// 添加工资记录
        /// </summary>
        /// <param name="salaryRecord">工资记录对象</param>
        /// <returns>新记录ID，失败返回0</returns>
        public long AddSalaryRecord(SalaryRecord salaryRecord)
        {
            if (salaryRecord == null)
                throw new ArgumentNullException("salaryRecord", "工资记录对象不能为空");

            if (salaryRecord.EmpId <= 0)
                throw new ArgumentException("员工ID无效");

            if (salaryRecord.ItemId <= 0)
                throw new ArgumentException("工资项目ID无效");

            if (string.IsNullOrEmpty(salaryRecord.YearMonth))
                throw new ArgumentException("年月不能为空");

            // 验证年月格式（YYYY-MM）
            if (!Regex.IsMatch(salaryRecord.YearMonth, @"^\d{4}-\d{2}$"))
                throw new ArgumentException("年月格式必须为YYYY-MM");

            // 检查员工是否存在
            Employee employee = _employeeDAL.GetEmployeeById(salaryRecord.EmpId);
            if (employee == null)
                throw new Exception("员工不存在");

            // 检查工资项目是否存在
            SalaryItem salaryItem = _salaryDAL.GetSalaryItemById(salaryRecord.ItemId);
            if (salaryItem == null)
                throw new Exception("工资项目不存在");

            return _salaryDAL.AddSalaryRecord(salaryRecord);
        }

        /// <summary>
        /// 批量添加工资记录
        /// </summary>
        /// <param name="salaryRecords">工资记录列表</param>
        /// <returns>成功添加的记录数</returns>
        public int BatchAddSalaryRecords(List<SalaryRecord> salaryRecords)
        {
            if (salaryRecords == null || salaryRecords.Count == 0)
                throw new ArgumentException("工资记录列表不能为空");

            // 此处可以添加更多验证逻辑

            return _salaryDAL.BatchAddSalaryRecords(salaryRecords);
        }

        /// <summary>
        /// 更新工资记录
        /// </summary>
        /// <param name="salaryRecord">工资记录对象</param>
        /// <returns>更新成功返回true，失败返回false</returns>
        public bool UpdateSalaryRecord(SalaryRecord salaryRecord)
        {
            if (salaryRecord == null)
                throw new ArgumentNullException("salaryRecord", "工资记录对象不能为空");

            if (salaryRecord.RecordId <= 0)
                throw new ArgumentException("工资记录ID无效");

            return _salaryDAL.UpdateSalaryRecord(salaryRecord);
        }

        /// <summary>
        /// 删除工资记录
        /// </summary>
        /// <param name="recordId">记录ID</param>
        /// <returns>删除成功返回true，失败返回false</returns>
        public bool DeleteSalaryRecord(long recordId)
        {
            if (recordId <= 0)
                throw new ArgumentException("无效的工资记录ID");

            return _salaryDAL.DeleteSalaryRecord(recordId);
        }

        /// <summary>
        /// 删除员工某月的所有工资记录
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月(YYYY-MM)</param>
        /// <returns>删除成功返回true，失败返回false</returns>
        public bool DeleteEmployeeSalaryRecords(int empId, string yearMonth)
        {
            if (empId <= 0)
                throw new ArgumentException("无效的员工ID");

            if (string.IsNullOrEmpty(yearMonth))
                throw new ArgumentException("年月不能为空");

            // 验证年月格式（YYYY-MM）
            if (!Regex.IsMatch(yearMonth, @"^\d{4}-\d{2}$"))
                throw new ArgumentException("年月格式必须为YYYY-MM");

            return _salaryDAL.DeleteEmployeeSalaryRecords(empId, yearMonth);
        }

        /// <summary>
        /// 获取员工某月的工资记录
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月(YYYY-MM)</param>
        /// <returns>工资记录列表</returns>
        public List<SalaryRecord> GetEmployeeSalaryRecords(int empId, string yearMonth)
        {
            if (empId <= 0)
                throw new ArgumentException("无效的员工ID");

            if (string.IsNullOrEmpty(yearMonth))
                throw new ArgumentException("年月不能为空");

            // 验证年月格式（YYYY-MM）
            if (!Regex.IsMatch(yearMonth, @"^\d{4}-\d{2}$"))
                throw new ArgumentException("年月格式必须为YYYY-MM");

            return _salaryDAL.GetEmployeeSalaryRecords(empId, yearMonth);
        }

        /// <summary>
        /// 获取某月所有员工的工资记录
        /// </summary>
        /// <param name="yearMonth">年月(YYYY-MM)</param>
        /// <returns>工资记录列表</returns>
        public List<SalaryRecord> GetMonthlySalaryRecords(string yearMonth)
        {
            if (string.IsNullOrEmpty(yearMonth))
                throw new ArgumentException("年月不能为空");

            // 验证年月格式（YYYY-MM）
            if (!Regex.IsMatch(yearMonth, @"^\d{4}-\d{2}$"))
                throw new ArgumentException("年月格式必须为YYYY-MM");

            return _salaryDAL.GetMonthlySalaryRecords(yearMonth);
        }

        /// <summary>
        /// 获取某部门某月的工资记录
        /// </summary>
        /// <param name="deptId">部门ID</param>
        /// <param name="yearMonth">年月(YYYY-MM)</param>
        /// <returns>工资记录列表</returns>
        public List<SalaryRecord> GetDepartmentSalaryRecords(int deptId, string yearMonth)
        {
            if (deptId <= 0)
                throw new ArgumentException("无效的部门ID");

            if (string.IsNullOrEmpty(yearMonth))
                throw new ArgumentException("年月不能为空");

            // 验证年月格式（YYYY-MM）
            if (!Regex.IsMatch(yearMonth, @"^\d{4}-\d{2}$"))
                throw new ArgumentException("年月格式必须为YYYY-MM");

            return _salaryDAL.GetDepartmentSalaryRecords(deptId, yearMonth);
        }

        /// <summary>
        /// 获取员工的历史工资记录
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <returns>工资记录列表，按年月倒序排列</returns>
        public List<SalaryRecord> GetEmployeeHistorySalaryRecords(int empId)
        {
            if (empId <= 0)
                throw new ArgumentException("无效的员工ID");

            return _salaryDAL.GetEmployeeHistorySalaryRecords(empId);
        }

        /// <summary>
        /// 获取可用的年月列表
        /// </summary>
        /// <returns>年月列表</returns>
        public List<string> GetAvailableYearMonths()
        {
            return _salaryDAL.GetAvailableYearMonths();
        }

        /// <summary>
        /// 导出工资数据到Excel
        /// </summary>
        /// <param name="yearMonth">年月</param>
        /// <returns>是否导出成功</returns>
        public bool ExportSalaryToExcel(string yearMonth)
        {
            try
            {
                if (string.IsNullOrEmpty(yearMonth))
                    return false;

                // 获取指定月份的所有工资记录
                List<SalaryRecord> records = _salaryDAL.GetMonthlySalaryRecords(yearMonth);
                if (records == null || records.Count == 0)
                    return false;

                // 调用导出工具
                return Utils.ExcelHelper.ExportSalaryToExcel(records, yearMonth);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 导出员工工资单为PDF
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月</param>
        /// <returns>是否导出成功</returns>
        public bool ExportEmployeeSalaryToPdf(int empId, string yearMonth)
        {
            try
            {
                if (empId <= 0 || string.IsNullOrEmpty(yearMonth))
                    return false;

                // 获取员工某月的工资记录
                List<SalaryRecord> records = _salaryDAL.GetEmployeeSalaryRecords(empId, yearMonth);
                if (records == null || records.Count == 0)
                    return false;

                // 调用导出工具
                return Utils.ExcelHelper.ExportEmployeeSalaryToPdf(empId, yearMonth, records);
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 计算员工某月的工资总额
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月</param>
        /// <returns>工资汇总信息</returns>
        public SalaryInfo CalculateEmployeeSalaryByYearMonth(int empId, string yearMonth)
        {
            if (empId <= 0)
                throw new ArgumentException("无效的员工ID");

            if (string.IsNullOrEmpty(yearMonth))
                throw new ArgumentException("年月不能为空");

            // 获取员工某月的工资记录
            List<SalaryRecord> records = _salaryDAL.GetEmployeeSalaryRecords(empId, yearMonth);
            
            // 计算总收入和总扣款
            decimal totalIncome = 0;
            decimal totalDeduction = 0;

            foreach (var record in records)
            {
                if (record.ItemType == "income")
                    totalIncome += record.Amount;
                else if (record.ItemType == "deduction")
                    totalDeduction += record.Amount;
            }

            // 创建并返回工资汇总信息
            SalaryInfo salaryInfo = new SalaryInfo();
            salaryInfo.EmpId = empId;
            salaryInfo.EmpName = records.Count > 0 ? records[0].EmpName : "";
            salaryInfo.DeptName = records.Count > 0 ? records[0].DeptName : "";
            salaryInfo.YearMonth = yearMonth;
            salaryInfo.TotalIncome = totalIncome;
            salaryInfo.TotalDeduction = totalDeduction;
            salaryInfo.NetSalary = totalIncome - totalDeduction;

            return salaryInfo;
        }
        
        /// <summary>
        /// 获取指定月份的所有工资记录
        /// </summary>
        /// <param name="yearMonth">年月 (YYYY-MM)</param>
        /// <returns>工资记录列表</returns>
        public List<SalaryRecord> GetSalaryByMonth(string yearMonth)
        {
            if (string.IsNullOrEmpty(yearMonth))
            {
                throw new ArgumentException("年月参数不能为空", nameof(yearMonth));
            }
            
            return _salaryDAL.GetSalaryByMonth(yearMonth);
        }
        
        /// <summary>
        /// 获取部门某月的工资信息
        /// </summary>
        /// <param name="deptId">部门ID，0表示所有部门</param>
        /// <param name="year">年份</param>
        /// <param name="month">月份</param>
        /// <returns>工资信息列表</returns>
        public List<SalaryInfo> GetSalaryByMonth(int deptId, int year, int month)
        {
            string yearMonth = $"{year}-{month:D2}";
            List<SalaryInfo> result = new List<SalaryInfo>();
            
            try
            {
                List<Employee> employees;
                
                if (deptId <= 0)
                {
                    // 获取所有员工
                    employees = _employeeDAL.GetAllEmployees();
                }
                else
                {
                    // 获取指定部门的员工
                    employees = _employeeDAL.GetEmployeesByDepartment(deptId);
                }
                
                // 获取每个员工的工资信息
                foreach (var employee in employees)
                {
                    try
                    {
                        SalaryInfo salaryInfo = GetSalaryByEmployeeAndMonth(employee.EmpId, yearMonth);
                        if (salaryInfo != null)
                        {
                            result.Add(salaryInfo);
                        }
                    }
                    catch
                    {
                        // 忽略单个员工获取失败的情况
                        continue;
                    }
                }
                
                return result;
            }
            catch (Exception ex)
            {
                throw new Exception($"获取工资信息失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 确认工资发放
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月(YYYY-MM格式)</param>
        /// <returns>是否确认成功</returns>
        public bool ConfirmSalaryPayment(int empId, string yearMonth)
        {
            if (empId <= 0)
            {
                throw new ArgumentException("员工ID无效");
            }

            if (string.IsNullOrEmpty(yearMonth) || !Regex.IsMatch(yearMonth, @"^\d{4}-\d{2}$"))
            {
                throw new ArgumentException("年月格式无效，应为YYYY-MM");
            }

            try
            {
                // 分解年月
                string[] parts = yearMonth.Split('-');
                int year = int.Parse(parts[0]);
                int month = int.Parse(parts[1]);

                // 获取员工信息
                var employee = _employeeDAL.GetEmployeeById(empId);
                if (employee == null)
                {
                    throw new Exception($"员工ID {empId} 不存在");
                }

                // 检查是否已经计算过工资
                var salaryRecords = _salaryDAL.GetEmployeeSalaryRecords(empId, yearMonth);
                if (salaryRecords == null || salaryRecords.Count == 0)
                {
                    // 尝试计算工资
                    var salaryInfo = CalculateSalary(empId, year, month);
                    if (salaryInfo == null)
                    {
                        throw new Exception($"无法计算员工 {employee.Name} 在 {yearMonth} 的工资");
                    }
                }

                // 标记工资已发放
                return _salaryDAL.ConfirmSalaryPayment(empId, yearMonth, DateTime.Now);
            }
            catch (Exception ex)
            {
                throw new Exception($"确认工资发放失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 确认部门或全体员工工资发放
        /// </summary>
        /// <param name="deptId">部门ID，0表示所有部门</param>
        /// <param name="year">年份</param>
        /// <param name="month">月份</param>
        /// <returns>是否确认成功</returns>
        public bool ConfirmSalaryPayment(int deptId, int year, int month)
        {
            string yearMonth = $"{year}-{month:D2}";
            
            try
            {
                List<Employee> employees;
                
                if (deptId <= 0)
                {
                    // 获取所有员工
                    employees = _employeeDAL.GetAllEmployees();
                }
                else
                {
                    // 获取指定部门的员工
                    employees = _employeeDAL.GetEmployeesByDepartment(deptId);
                }
                
                if (employees == null || employees.Count == 0)
                {
                    return false;
                }
                
                int successCount = 0;
                
                // 确认每个员工的工资
                foreach (Employee employee in employees)
                {
                    try
                    {
                        if (_salaryDAL.ConfirmSalaryPayment(employee.EmpId, yearMonth, DateTime.Now))
                        {
                            successCount++;
                        }
                    }
                    catch
                    {
                        // 忽略个别员工确认失败
                        continue;
                    }
                }
                
                return successCount > 0;
            }
            catch (Exception ex)
            {
                throw new Exception($"确认部门工资发放失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 获取员工指定月份的工资信息
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月格式(YYYY-MM)</param>
        /// <returns>工资信息</returns>
        public SalaryInfo GetSalaryByEmployeeAndMonth(int empId, string yearMonth)
        {
            // 检查参数
            if (empId <= 0)
            {
                throw new ArgumentException("员工ID无效");
            }

            if (string.IsNullOrEmpty(yearMonth) || !System.Text.RegularExpressions.Regex.IsMatch(yearMonth, @"^\d{4}-\d{2}$"))
            {
                throw new ArgumentException("年月格式无效，应为YYYY-MM");
            }

            // 获取员工信息
            Employee employee = _employeeDAL.GetEmployeeById(empId);
            if (employee == null)
            {
                throw new Exception($"员工ID {empId} 不存在");
            }

            // 获取该员工该月份的工资记录
            List<SalaryRecord> records = _salaryDAL.GetEmployeeSalaryRecords(empId, yearMonth);
            if (records == null || records.Count == 0)
            {
                // 没有找到工资记录
                return null;
            }

            // 解析年月
            string[] parts = yearMonth.Split('-');
            int year = int.Parse(parts[0]);
            int month = int.Parse(parts[1]);

            // 创建工资信息对象
            SalaryInfo salaryInfo = new SalaryInfo
            {
                EmpId = empId,
                EmpName = employee.Name,
                EmpNumber = employee.EmpNumber,
                DeptId = employee.DeptId,
                DeptName = employee.DeptName,
                Position = employee.Position,
                Year = year,
                Month = month,
                BaseSalary = 0,
                PositionAllowance = 0,
                PerformanceBonus = 0,
                OvertimePay = 0,
                SocialInsurance = 0,
                HousingFund = 0,
                IncomeTax = 0,
                AbsenceDeduction = 0,
                OtherDeductions = 0,
                TotalIncome = 0,
                TotalDeduction = 0,
                NetSalary = 0,
                CalculateDate = DateTime.Now
            };

            // 汇总工资记录
            foreach (var record in records)
            {
                switch (record.ItemName)
                {
                    case "基本工资":
                        salaryInfo.BaseSalary = record.Amount;
                        salaryInfo.TotalIncome += record.Amount;
                        break;
                    case "岗位津贴":
                        salaryInfo.PositionAllowance = record.Amount;
                        salaryInfo.TotalIncome += record.Amount;
                        break;
                    case "绩效奖金":
                        salaryInfo.PerformanceBonus = record.Amount;
                        salaryInfo.TotalIncome += record.Amount;
                        break;
                    case "加班工资":
                        salaryInfo.OvertimePay = record.Amount;
                        salaryInfo.TotalIncome += record.Amount;
                        break;
                    case "社会保险":
                        salaryInfo.SocialInsurance = record.Amount;
                        salaryInfo.TotalDeduction += record.Amount;
                        break;
                    case "住房公积金":
                        salaryInfo.HousingFund = record.Amount;
                        salaryInfo.TotalDeduction += record.Amount;
                        break;
                    case "个人所得税":
                        salaryInfo.IncomeTax = record.Amount;
                        salaryInfo.TotalDeduction += record.Amount;
                        break;
                    case "缺勤扣款":
                        salaryInfo.AbsenceDeduction = record.Amount;
                        salaryInfo.TotalDeduction += record.Amount;
                        break;
                    case "其他扣款":
                        salaryInfo.OtherDeductions = record.Amount;
                        salaryInfo.TotalDeduction += record.Amount;
                        break;
                }
            }

            // 计算实发工资
            salaryInfo.NetSalary = salaryInfo.TotalIncome - salaryInfo.TotalDeduction;

            return salaryInfo;
        }

        /// <summary>
        /// 计算单个员工工资
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="year">年份</param>
        /// <param name="month">月份</param>
        /// <returns>工资信息</returns>
        public SalaryInfo CalculateSalary(int empId, int year, int month)
        {
            if (empId <= 0)
            {
                throw new ArgumentException("员工ID无效");
            }
            
            // 1. 检查员工是否存在
            Employee employee = _employeeDAL.GetEmployeeById(empId);
            if (employee == null)
            {
                throw new Exception($"找不到ID为{empId}的员工");
            }
            
            // 2. 检查该员工该月工资是否已计算
            string yearMonth = $"{year}-{month:D2}";
            if (_salaryDAL.CheckSalaryExists(empId, yearMonth))
            {
                // 直接返回已计算的工资信息
                return GetSalaryByEmployeeAndMonth(empId, yearMonth);
            }
            
            // 3. 计算工资信息
            SalaryInfo salaryInfo = CalculateEmployeeSalary(employee, year, month);
            
            // 4. 保存工资信息
            SaveSalaryRecords(salaryInfo);
            
            return salaryInfo;
        }
        
        /// <summary>
        /// 批量计算指定部门或全部员工的工资
        /// </summary>
        /// <param name="deptId">部门ID，0表示所有部门</param>
        /// <param name="year">年份</param>
        /// <param name="month">月份</param>
        /// <returns>计算成功的员工数量</returns>
        public int BatchCalculateSalary(int deptId, int year, int month)
        {
            List<Employee> employees;
            
            // 获取要计算工资的员工列表
            if (deptId <= 0)
            {
                // 获取所有员工
                employees = _employeeDAL.GetAllEmployees();
            }
            else
            {
                // 检查部门是否存在
                Department department = _departmentDAL.GetDepartmentById(deptId);
                if (department == null)
                {
                    throw new Exception($"找不到ID为{deptId}的部门");
                }
                
                // 获取指定部门的员工
                employees = _employeeDAL.GetEmployeesByDepartment(deptId);
            }
            
            if (employees == null || employees.Count == 0)
            {
                throw new Exception("没有找到需要计算工资的员工");
            }
            
            int successCount = 0;
            List<Exception> errors = new List<Exception>();
            
            // 批量计算工资
            foreach (Employee employee in employees)
            {
                try
                {
                    // 检查该员工该月工资是否已计算
                    string yearMonth = $"{year}-{month:D2}";
                    if (_salaryDAL.CheckSalaryExists(employee.EmpId, yearMonth))
                    {
                        // 已计算，跳过
                        successCount++;
                        continue;
                    }
                    
                    // 计算工资
                    SalaryInfo salaryInfo = CalculateEmployeeSalary(employee, year, month);
                    
                    // 保存工资信息
                    SaveSalaryRecords(salaryInfo);
                    
                    successCount++;
                }
                catch (Exception ex)
                {
                    // 记录错误，继续处理其他员工
                    errors.Add(new Exception($"计算员工[{employee.EmpId}]{employee.EmpName}的工资时出错: {ex.Message}", ex));
                }
            }
            
            // 如果全部失败，抛出异常
            if (successCount == 0 && errors.Count > 0)
            {
                throw new Exception($"批量计算工资失败: {errors[0].Message}");
            }
            
            return successCount;
        }
        
        /// <summary>
        /// 计算员工工资详情
        /// </summary>
        /// <param name="employee">员工对象</param>
        /// <param name="year">年份</param>
        /// <param name="month">月份</param>
        /// <returns>工资信息</returns>
        private SalaryInfo CalculateEmployeeSalary(Employee employee, int year, int month)
        {
            if (employee == null)
            {
                throw new ArgumentNullException(nameof(employee));
            }
            
            // 创建工资信息对象
            SalaryInfo salaryInfo = new SalaryInfo
            {
                EmpId = employee.EmpId,
                EmpName = employee.EmpName,
                EmpNumber = employee.EmpNumber,
                DeptId = employee.DeptId,
                DeptName = employee.DeptName,
                Year = year,
                Month = month,
                Position = employee.Position,
                BaseSalary = employee.BaseSalary,
                CalculateDate = DateTime.Now
            };
            
            // 1. 获取员工考勤信息
            AttendanceInfo attendance = _attendanceDAL.GetAttendanceByEmployee(employee.EmpId, year, month);
            
            // 2. 计算工资组成部分
            
            // 2.1 基本工资部分
            decimal baseSalary = employee.BaseSalary;
            
            // 2.2 职位津贴
            decimal positionAllowance = CalculatePositionAllowance(employee.Position, baseSalary);
            
            // 2.3 绩效奖金
            decimal performanceBonus = CalculatePerformanceBonus(employee.EmpId, year, month);
            
            // 2.4 加班费
            decimal overtimePay = 0;
            if (attendance != null)
            {
                overtimePay = CalculateOvertimePay(attendance.OvertimeHours, baseSalary);
            }
            
            // 2.5 社保和公积金(个人部分)
            decimal socialInsurance = CalculateSocialInsurance(baseSalary);
            decimal housingFund = CalculateHousingFund(baseSalary);
            
            // 2.6 税前工资
            decimal preTaxSalary = baseSalary + positionAllowance + performanceBonus + overtimePay;
            
            // 2.7 计算个税
            decimal incomeTax = CalculateIncomeTax(preTaxSalary - socialInsurance - housingFund);
            
            // 2.8 缺勤扣款
            decimal absenceDeduction = 0;
            if (attendance != null)
            {
                absenceDeduction = CalculateAbsenceDeduction(attendance.AbsenceDays, baseSalary);
            }
            
            // 2.9 其他扣款
            decimal otherDeductions = 0; // 可根据需求添加其他扣款项
            
            // 3. 计算总收入、总扣款和实发工资
            salaryInfo.BaseSalary = baseSalary;
            salaryInfo.PositionAllowance = positionAllowance;
            salaryInfo.PerformanceBonus = performanceBonus;
            salaryInfo.OvertimePay = overtimePay;
            salaryInfo.TotalIncome = preTaxSalary;
            
            salaryInfo.SocialInsurance = socialInsurance;
            salaryInfo.HousingFund = housingFund;
            salaryInfo.IncomeTax = incomeTax;
            salaryInfo.AbsenceDeduction = absenceDeduction;
            salaryInfo.OtherDeductions = otherDeductions;
            salaryInfo.TotalDeduction = socialInsurance + housingFund + incomeTax + absenceDeduction + otherDeductions;
            
            salaryInfo.NetSalary = salaryInfo.TotalIncome - salaryInfo.TotalDeduction;
            
            return salaryInfo;
        }
        
        /// <summary>
        /// 计算岗位津贴
        /// </summary>
        private decimal CalculatePositionAllowance(string position, decimal baseSalary)
        {
            decimal _allowanceRate = 0.0m;
            
            switch (position?.ToLower())
            {
                case "总经理":
                    _allowanceRate = 0.5m;
                    break;
                case "副总经理":
                    _allowanceRate = 0.4m;
                    break;
                case "部门经理":
                    _allowanceRate = 0.3m;
                    break;
                case "主管":
                case "team leader":
                    _allowanceRate = 0.2m;
                    break;
                case "高级工程师":
                    _allowanceRate = 0.15m;
                    break;
                case "工程师":
                    _allowanceRate = 0.1m;
                    break;
                default:
                    _allowanceRate = 0.05m;
                    break;
            }
            
            return Math.Round(baseSalary * _allowanceRate, 2);
        }
        
        /// <summary>
        /// 计算绩效奖金
        /// </summary>
        private decimal CalculatePerformanceBonus(int empId, int year, int month)
        {
            // 这里可以从绩效评估系统获取数据
            // 简化处理，返回固定金额
            return 1000m;
        }
        
        /// <summary>
        /// 计算加班费
        /// </summary>
        private decimal CalculateOvertimePay(decimal overtimeHours, decimal baseSalary)
        {
            // 基本工资 / (21.75 * 8) * 1.5 * 加班小时数
            decimal hourlyRate = baseSalary / (21.75m * 8);
            return Math.Round(hourlyRate * 1.5m * overtimeHours, 2);
        }
        
        /// <summary>
        /// 计算社保(个人部分)
        /// </summary>
        private decimal CalculateSocialInsurance(decimal baseSalary)
        {
            // 假设社保个人缴纳比例为10.5%
            return Math.Round(baseSalary * 0.105m, 2);
        }
        
        /// <summary>
        /// 计算住房公积金(个人部分)
        /// </summary>
        private decimal CalculateHousingFund(decimal baseSalary)
        {
            // 假设公积金个人缴纳比例为12%
            return Math.Round(baseSalary * 0.12m, 2);
        }
        
        /// <summary>
        /// 计算个人所得税(简化)
        /// </summary>
        private decimal CalculateIncomeTax(decimal taxableIncome)
        {
            // 个税起征点5000元
            decimal threshold = 5000m;
            
            if (taxableIncome <= threshold)
            {
                return 0;
            }
            
            decimal taxableAmount = taxableIncome - threshold;
            decimal tax = 0;
            
            // 使用2019年新个税税率表(简化处理)
            if (taxableAmount <= 3000)
            {
                tax = taxableAmount * 0.03m;
            }
            else if (taxableAmount <= 12000)
            {
                tax = taxableAmount * 0.1m - 210;
            }
            else if (taxableAmount <= 25000)
            {
                tax = taxableAmount * 0.2m - 1410;
            }
            else if (taxableAmount <= 35000)
            {
                tax = taxableAmount * 0.25m - 2660;
            }
            else if (taxableAmount <= 55000)
            {
                tax = taxableAmount * 0.3m - 4410;
            }
            else if (taxableAmount <= 80000)
            {
                tax = taxableAmount * 0.35m - 7160;
            }
            else
            {
                tax = taxableAmount * 0.45m - 15160;
            }
            
            return Math.Round(tax, 2);
        }
        
        /// <summary>
        /// 计算缺勤扣款
        /// </summary>
        private decimal CalculateAbsenceDeduction(decimal absenceDays, decimal baseSalary)
        {
            // 每天扣款 = 基本工资 / 21.75
            decimal dailyRate = baseSalary / 21.75m;
            return Math.Round(dailyRate * absenceDays, 2);
        }

        /// <summary>
        /// 保存工资记录
        /// </summary>
        /// <param name="salaryInfo">工资信息对象</param>
        private void SaveSalaryRecords(SalaryInfo salaryInfo)
        {
            // 首先删除该员工当月的所有工资记录
            string yearMonth = salaryInfo.YearMonth;
            _salaryDAL.DeleteEmployeeSalaryRecords(salaryInfo.EmpId, yearMonth);
            
            // 获取所有工资项目
            List<SalaryItem> salaryItems = _salaryDAL.GetAllSalaryItems();
            
            // 创建工资记录列表
            List<SalaryRecord> records = new List<SalaryRecord>();
            
            // 添加各项收入
            // 基本工资
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "基本工资", salaryInfo.BaseSalary);
            
            // 岗位津贴
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "岗位津贴", salaryInfo.PositionAllowance);
            
            // 绩效奖金
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "绩效奖金", salaryInfo.PerformanceBonus);
            
            // 加班工资
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "加班工资", salaryInfo.OvertimePay);
            
            // 添加各项扣款
            // 社会保险
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "社会保险", salaryInfo.SocialInsurance);
            
            // 住房公积金
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "住房公积金", salaryInfo.HousingFund);
            
            // 个人所得税
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "个人所得税", salaryInfo.IncomeTax);
            
            // 缺勤扣款
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "缺勤扣款", salaryInfo.AbsenceDeduction);
            
            // 其他扣款
            AddSalaryRecordIfExists(records, salaryInfo.EmpId, yearMonth, salaryItems, "其他扣款", salaryInfo.OtherDeductions);
            
            // 批量添加工资记录
            if (records.Count > 0)
            {
                _salaryDAL.BatchAddSalaryRecords(records);
            }
        }
        
        /// <summary>
        /// 如果工资项存在且金额不为零，则添加工资记录
        /// </summary>
        private void AddSalaryRecordIfExists(List<SalaryRecord> records, int empId, string yearMonth, 
            List<SalaryItem> salaryItems, string itemName, decimal amount)
        {
            if (amount != 0)
            {
                SalaryItem item = salaryItems.Find(i => i.ItemName == itemName);
                if (item != null)
                {
                    records.Add(new SalaryRecord
                    {
                        EmpId = empId,
                        ItemId = item.ItemId,
                        YearMonth = yearMonth,
                        Amount = amount,
                        CreatedTime = DateTime.Now,
                        UpdatedTime = DateTime.Now
                    });
                }
            }
        }

        /// <summary>
        /// 获取员工工资信息
        /// </summary>
        /// <param name="empId">员工ID</param>
        /// <param name="yearMonth">年月（格式：YYYY-MM）</param>
        /// <returns>工资信息对象</returns>
        public SalaryInfo GetEmployeeSalary(int empId, string yearMonth)
        {
            if (empId <= 0)
                throw new ArgumentException("员工ID无效", nameof(empId));

            if (string.IsNullOrEmpty(yearMonth))
                throw new ArgumentException("年月不能为空", nameof(yearMonth));

            try
            {
                // 解析年月
                string[] parts = yearMonth.Split('-');
                if (parts.Length != 2 || !int.TryParse(parts[0], out int year) || !int.TryParse(parts[1], out int month))
                    throw new ArgumentException("年月格式不正确，应为YYYY-MM", nameof(yearMonth));

                // 获取该员工的工资记录
                List<SalaryRecord> records = _salaryDAL.GetEmployeeSalaryRecords(empId, yearMonth);
                
                if (records == null || records.Count == 0)
                    return null;

                // 获取员工信息
                Employee employee = _employeeDAL.GetEmployeeById(empId);
                if (employee == null)
                    throw new Exception($"找不到ID为 {empId} 的员工");

                // 创建工资信息对象
                SalaryInfo salaryInfo = new SalaryInfo
                {
                    EmpId = empId,
                    EmpName = employee.Name,
                    EmpNumber = employee.EmpNumber,
                    DeptId = employee.DeptId,
                    DeptName = employee.DeptName,
                    Year = year,
                    Month = month,
                    Position = employee.Position,
                    BaseSalary = 0,
                    PositionAllowance = 0,
                    PerformanceBonus = 0,
                    OvertimePay = 0,
                    SocialInsurance = 0,
                    HousingFund = 0,
                    IncomeTax = 0,
                    AbsenceDeduction = 0,
                    OtherDeductions = 0,
                    TotalIncome = 0,
                    TotalDeduction = 0,
                    NetSalary = 0
                };

                // 汇总工资记录中的各项金额
                foreach (var record in records)
                {
                    if (string.IsNullOrEmpty(record.ItemType))
                        continue;

                    // 根据工资项类型和名称设置对应的属性
                    switch (record.ItemName)
                    {
                        case "基本工资":
                            salaryInfo.BaseSalary = record.Amount;
                            break;
                        case "岗位津贴":
                            salaryInfo.PositionAllowance = record.Amount;
                            break;
                        case "绩效奖金":
                            salaryInfo.PerformanceBonus = record.Amount;
                            break;
                        case "加班工资":
                            salaryInfo.OvertimePay = record.Amount;
                            break;
                        case "社会保险":
                            salaryInfo.SocialInsurance = record.Amount;
                            break;
                        case "住房公积金":
                            salaryInfo.HousingFund = record.Amount;
                            break;
                        case "个人所得税":
                            salaryInfo.IncomeTax = record.Amount;
                            break;
                        case "缺勤扣款":
                            salaryInfo.AbsenceDeduction = record.Amount;
                            break;
                        case "其他扣款":
                            salaryInfo.OtherDeductions = record.Amount;
                            break;
                    }

                    // 累计收入和扣款
                    if (record.ItemType.Equals("income", StringComparison.OrdinalIgnoreCase))
                        salaryInfo.TotalIncome += record.Amount;
                    else if (record.ItemType.Equals("deduction", StringComparison.OrdinalIgnoreCase))
                        salaryInfo.TotalDeduction += record.Amount;
                }

                // 计算实发工资
                salaryInfo.NetSalary = salaryInfo.TotalIncome - salaryInfo.TotalDeduction;

                return salaryInfo;
            }
            catch (Exception ex)
            {
                throw new Exception($"获取员工工资信息失败: {ex.Message}", ex);
            }
        }
        
        #endregion
    }
} 